﻿using System;
using System.Collections.Generic;
using FinPlusComponents;
using QLNet;
using p = FinPlusAnalytics.QLConvParser;

namespace FinPlusAnalytics
{
    public class FloatingRateBondBuild : FinPlusComponent
    {
        public RelinkableHandle<Quote> Spread { get; private set; }

        //construct
        public FloatingRateBondBuild(string marketName, string name, double spread, string curveName, string indexName, string couponFrq, 
            double redemption, int settlementDays, DateTime effectiveDate, DateTime terminationDate, string dayCount, string payConv,
            string termConv, string bondConv, string holidays, int fixingDays = 2, bool inArrears = true, bool endOfMonth = false)
        {
            var market = Markets.Instance.GetMarket(marketName);

            var index = market.GetIndex(indexName);
            Spread = market.GetQuote(name);
            Spread.linkTo(new SimpleQuote(spread));

            var calendar = p.Calendar(holidays);

		    var schedule = new  Schedule(effectiveDate, terminationDate, new Period(p.Freq(couponFrq)), calendar, 
                p.BizConv(payConv), p.BizConv(termConv), DateGeneration.Rule.Backward, endOfMonth);
		    
            var bond =  new QLNet.FloatingRateBond(settlementDays, 100, schedule, index,  p.DayCount(dayCount), p.BizConv(bondConv), 
                fixingDays, new List<double>() {1 }, new List<double>(){spread}, new List<double>(), new List<double>(), inArrears, redemption, effectiveDate);
     
		    // optionLet volatilities
            var volatility = new Handle<OptionletVolatilityStructure>(new ConstantOptionletVolatility(settlementDays, calendar, 
                BusinessDayConvention.ModifiedFollowing, 0.0, new Actual365Fixed()));
           
		    // Coupon pricers
		    var iborCouponPricer = new BlackIborCouponPricer();
            iborCouponPricer.setCapletVolatility(volatility);
            Utils.setCouponPricer(bond.cashflows(), iborCouponPricer);

            market.GetBond(name).linkTo(bond);
        }
    }
}
